package com.rain.cy.framework.aspect;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rain.cy.framework.entity.BaseController;
import com.rain.cy.framework.result.ErrorCodeEnum;
import com.rain.cy.framework.result.ResultUtil;
import com.rain.cy.framework.utils.SendMsgUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author richrain.cy
 * @date 2021/8/12 4:34 下午
 */
@Aspect
@Slf4j
@Component
public class ExceptionAspect extends BaseController {


    /**
     * 过程中监测，catch到异常之后返回包装后的错误信息，并打印日志
     */
    @Around(value = "execution(public * com.rain.cy.business.controller.*.*(..))")
    public Object catchException(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Class<?> targetClass = method.getDeclaringClass();
        String requestMethod = targetClass.getName() + "#" + method.getName();
        String requestParam = JSON.toJSONString(joinPoint.getArgs());
        try {
            printInfoLog(requestMethod, requestParam, "");
            Object proceed = joinPoint.proceed();
            printInfoLog(requestMethod, requestParam, JSONObject.toJSONString(proceed));
            return proceed;
        } catch (Throwable e) {
            printErrorLog(requestMethod, requestParam, ExceptionUtils.getStackFrames(e));
            if (e instanceof IllegalArgumentException) {
                return ResultUtil.failWithErrorStack(ExceptionUtil.getSimpleMessage(e), ExceptionUtils.getStackTrace(e));
            }
            return ResultUtil.failWithErrorStack(ExceptionUtils.getStackTrace(e));
        }
    }


    private void printInfoLog(String requestMethod, String requestParam, String response) {
        log.info("\nrequestMethod={},\nrequestParam={},\nresponse={}", requestMethod, requestParam, response);
    }

    private void printErrorLog(String requestMethod, String requestParam, String[] errorInfo) {
        String msg = "\n●requestHost=%s\n●requestIp=%s\n●loginUserId=%s\n●requestMethod=%s\n●requestParam=%s\n●errorInfo=%s\n";
        String sendMsg = String.format(msg, request().getRemoteHost(), request().getRemoteAddr(), request().getHeader("userId"), requestMethod, requestParam, errorInfo[0]);
        StringBuilder stringBuffer = new StringBuilder(sendMsg);
        for (int i = 1; i < 10; i++) {
            stringBuffer.append(errorInfo[i]).append("\n");
        }
        ThreadUtil.execute(() -> SendMsgUtils.sendDingtalkMsg(stringBuffer.toString()));
        log.info("\nrequestMethod={},\nrequestParam={},\nerrorInfo=\n{}", requestMethod, requestParam, errorInfo);
    }

}
